"""
Автономно собираемый список команд.

Плагин формирует список команд и плагинов.
- Памятка по использованию Чио (/help help)
- Поиск по названию команды или плагина
- Справка по использованию команд
- Выдача команд без описания
- Отдельно вынесенная команда поиска
- Выдача случайной команды
- список плагинов:
  * сортируется по количеству команд
  * плагины у которых меньше 2х команд считаются утилитами
  * пометка команд для администраторов
- информация о плагине:
  * имя плагина, pid, количествово: обработчиков, коман и имён команд
  * описание плагина и аргументы команд
  * пометка команд для администраторов
  * группировка по проверющим и отрицающим функциям

Author: Milinuri Nirvalen
Ver: 2.4 (16)
"""

from chiori import Plugin
from libs.commands import gen_lib
from libs.commands import get_all_commands
from libs.commands import get_all_names
from libs.commands import get_pid
from libs.commands import get_random_cmd
from libs.commands import search


p = Plugin(name='автоинструкции плагинам',
	desc='создание автоматических инструкций к плагинам',
	args={'pattern':'regex шаблон для поиска'})

helptext = '''немного о том, как пользоваться Чио:
строение обращения:
* [ИМЯ][ПРЕФИКС ПЛАГИНА][КОМАНДА] [АРГУМЕНТЫ] (/help help)
-- имя - имя Чио: /, чио, chio... (/names - посмотреть спсок имён)
-- у плагина могут быть преффиксы. чтобы не пересекались команды (/rps stats. rps - преффмк)
-- название команды (help, apple, чат...)
* до названия команды также может быть текст. (список плагинов. плагинов - команда)
* вы можете вставлять "-" в название команд (chat-members = chatmembers)
- аргументы: <обязательные> [необязательные] (1, aaa...)

синтаксис описания команд:
* пример: <c(hat/hats) m(members)/users> --> cm, mc, cusers, users-chat...
-- <A B>: A и B в любом порядке (AB, BA)
-- <A/B C>: (A или B) и С (AC, CA, BC, BC)
-- A(B/C): A, AB, AC

использование /help
-- /help - список плагинов
пример: 19 [chat_control] чат: контроллер
-- 19 - спико команд
- [chat_control] - ID плагина (используется БЕЗ кваратных скобок)
- чат: контроллер - имя плагина

-- /help <plugin_name или plugin_ID> - информация о плагине
-- /help help - вывести эту справку
-- /help <command> - информация о команде'''

# commands
# ========

@p.command('plugin(s)', 'плагин(ы/ов)', 'help', 'помошь', '?',
	'команды', 'command(s)', 'cmds',
	usage='[pattern] список плагинов/команд плагина')
async def pluginsList(event, ctx):
	lib = gen_lib(ctx.app)
	text = ''

	if ctx.sargs:
		res = get_pid(lib, ctx.sargs)
		cl = get_all_names(lib)

		if ctx.sargs == 'help':
			return await ctx.message(helptext)

		if ctx.sargs in cl:
			cmd = cl[ctx.sargs]
			if cmd.get('admins'):
				level = f'🔶'
			else:
				level = '🔷'

			func = ''
			for g in ['check_func', 'else_func']:

				for k, v in cmd[g]:
					func += f' {k}'

				if cmd[g]:
					func += '; '
			if func:
				text += f'\n⚙ {func}\n'

			names = ', '.join(sorted(cmd["names"]))

			if len(cmd["names"]) > 2:
				text += f'\n{level} {names}\n-- {cmd["usage"]}\n'
			else:
				text += f'\n{level} {names}: {cmd["usage"]}\n'


		if len(res) == 1:
			v = lib[res[0]]
			if v.get('admins'):
				level = '🔥'
			else:
				level = ''

			text += f'\n[{res[0]}]: {level} {v["name"]}\n🧹 обработчиков:'

			for k, c in v["handlers"].items():
				text += f' | {k[0]}:{len(c)}'

			text += f'\n📦 команд: {len(v["routers"])} ({len(v["triggers"])} имён)'

			sp = v.get('sp', [])
			if sp:
				text += f'\n✏ префиксы плагина: {", ".join(sp)}'

			text += f'''\n📝 описание плагина: {v.get("desc", "нет описания")}'''

			if v.get('check_funcs'):
				text += f'\n📦 проверяющие функции ({len(v["check_funcs"])}):'
				for x in v["check_funcs"]:
					text += f'\n⚙ {x}'

			if v.get('args'):
				text += f'\n\n⚙ параметры команд:'
				for n, d in v.get('args', {}).items():
					text += f'\n♦ [ {n} ]: {d}'

			groups = {}

			# sorted(v['routers'].items(), key=lambda x: len(x[1]["names"]), reverse=True):

			for p, u in v["routers"].items():
				g_name = ''
				for x in u["check_func"]:
					g_name += ' ' + list(x)[0]
				for x in u["else_func"]:
					g_name += ' ' + list(x)[0]

				if g_name not in groups:
					groups[g_name] = [u]
				else:
					groups[g_name].append(u)

			for g, i in groups.items():

				if g:
					text += f'\n\n⚙ [{g} ]'
				else:
					text += f'\n\nкоманды:'

				for u in sorted(i, key=lambda x: len(x["names"]), reverse=True):
					if u.get('admins'):
						level = f'🔶'
					else:
						level = '🔷'

					names = ', '.join(sorted(u["names"]))
					text += f'\n{level} {names} - {u["usage"]}'

			text += f'\n\n💡 /help <cmd> - информация о комаеде'

		else:
			text += f'\n{search(lib, ctx.sargs)}'

	else:
		text = f'список плагинов ({len(ctx.app.plugins)} шт.) {len(get_all_commands(lib))} команд:'
		row = False

		for k, v in sorted(lib.items(), key=lambda x: x[1]['commands'], reverse=True):
			if v.get("admins") and event.get('level') != 10:
				continue

			if k.split(':')[1] == 'main':
				pid = k.split(':')[0]
			else:
				pid = k

			if len(str(v["commands"])) == 1:
				commands = f'0{v["commands"]}'
			else:
				commands = v["commands"]

			# decor level
			if v.get('admins'):
				level = '🔥'
			elif v["commands"] > 1:
				level = '📦'
			else:
				if not row:
					row = True
					text += f'\n\n⚙ утилиты:'
				level = ''

			if not row:
				text += f'\n-- {level} {commands} [{pid}] {v.get("name")}'
			else:
				text += f'\n-- [{pid}] {v.get("name")}'

		text += f'\n\n💡 /help help - спрака по автоинструкциям'

	await ctx.message(text)


@p.command('no-desc-cmd', admins=True, usage='список комманд без описания')
async def noDescCommands(event, ctx):
	lib = gen_lib(ctx.app)
	text = 'команды без описания:'

	for k, v in lib.items():
		group = False
		group_items = ''
		for pid, usage in v["routers"].items():
			if not usage["usage"]:
				group = True
				group_items += f'\n-- {" ".join(usage["names"])}'

		if group:
			text += f'\n📄 {v["pid"]}'
			text += group_items
			text += '\n'

	await ctx.message(text)


@p.command('<help/h search>', 'поиск', usage='[pattern] поиск по Чио')
async def chioSearch(event, ctx):
	await ctx.message(search(gen_lib(ctx.app), ctx.sargs))

@p.command('<r(andom) cmd/commad>', usage='случайная команда')
async def randomCommand(event, ctx):
	cmd = get_random_cmd(gen_lib(ctx.app))
	text = f'🎲 случайная команда:\n🔘 {cmd["id"]}'

	func = ''
	for g in ['check_func', 'else_func']:

		for k, v in cmd[g]:
			func += f' {k}'

		if cmd[g]:
			func += '; '

	if func:
		text += f'\n⚙ {func}\n'


	if cmd.get('admins'):
		level = f'🔶'
	else:
		level = '🔷'

	names = ', '.join(sorted(cmd["names"]))

	if len(cmd["names"]) > 2:
		text += f'\n{level} {names}\n-- {cmd["usage"]}'
	else:
		text += f'\n{level} {names} - {cmd["usage"]}\n'

	await ctx.message(text)

@p.command('<c/cmd/com(mand) g/gen(erator)>',
	usage='[text] использовать генератор имён команд чио для просмотра всех возможноыъ названий команд')
async def comGenerator(event, ctx):
	commands = []
	for cmd in p.convert_names([ctx.sargs], False):
		if not cmd:
			continue

		if cmd and cmd[0] == '<' and cmd[-1] == '>':
			cmds = cmd[1:-1].split(' ')

			for r in p.gen_names(
				p.convert_names(cmds[0].split('/')),
				p.convert_names(cmds[1].split('/'))):
				commands.append(r)
		else:
			commands.append(cmd)

	commands = sorted(commands, key=lambda x: len(x))
	await ctx.message(f'{ctx.sargs} -> {", ".join(commands)}')
